﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Globalization;

namespace AnalizadorCsv.Clases
{
    public class DefaultCsv
    {
        public int numeroColumnas;
        public List<String> titulos;
        public List<data> filas;
        private String archivo;
        private String archivoError;

        public DefaultCsv(String archivo, String archivoError)
        {
            this.archivo = archivo;
            this.archivoError = archivoError;
        }
        public void generarLogError(String error)
        {
            StreamWriter sw = new StreamWriter(this.archivoError, true, Encoding.Default);
            sw.WriteLine("(" + DateTime.Now.ToString() + ") - " + error);
            sw.Close();
        }
        private bool hayComas(String valor)
        {
            String[] valores = valor.Split(',');
            return valores.Length > 1;
        }
        private String acomodarValor(String valor)
        {
            String aux=valor;
            if (aux.Length > 0)
            {
                if (aux[0] == '\"' && aux[aux.Length - 1] == '\"')
                {
                    if (!hayComas(aux))
                    {
                        aux = aux.Substring(1, aux.Length - 2);
                    }
                }
            }
            return aux;
        }
        private void analizarColumnas()
        {
            foreach (data d in filas)
            {
                for (int i = 0; i < d.columna.Count; i++)
                {
                    String valor = acomodarValor(d.columna[i]);
                    d.columna[i] = valor;
                }
            }
        }
        public bool existeColumna(String titulo)
        {
            return titulos.IndexOf(titulo) != -1;
        }
        private int darColumnaPorTitulo(String titulo)
        {
            return titulos.IndexOf(titulo);
        }
        /*
         * 1- MM/DD/YYYY
         * 
         */
        private String obtenerFormatoCorrecto(String fecActual)
        {
            String aux = fecActual.Replace('\"',' ');
          
            return aux;
        }
        public bool acomodarporFechaHora(String titulo)
        {
            bool error = true;
            int col = this.darColumnaPorTitulo(titulo);
            if (col == -1)
            {
                generarLogError("[" + titulo + "] (Linea: " + (1) + ") Este campo no existe");
                return false;
            }
            for (int i = 0; i < filas.Count; i++)
            {
                data d = filas[i];
                bool errorX = false;
                String fechaOriginal = d.columna[col];
                if (d.columna[col].Length > 7)
                {
                    try
                    {
                        //d.columna[col] = d.columna[col].Replace("-", "/");
                        fechaOriginal = d.columna[col];
                        DateTime fech = new DateTime();
                        CultureInfo cultura = new CultureInfo("en-US");
                        try
                        {
                            errorX = false;
                            d.columna[col] = obtenerFormatoCorrecto(d.columna[col]);
                            fech = DateTime.Parse(d.columna[col], cultura);
                        }
                        catch (Exception e1)
                        {
                            Console.WriteLine("No Paso la prueba (YYYY/MM/DD)");
                            d.columna[col] = fechaOriginal;
                            errorX = true;
                        }
                        /*try
                        {
                            fech = DateTime.Parse(d.columna[col]);
                        }
                        catch (Exception e1)
                        {
                            Console.WriteLine(e1.Message);
                        }*/
                        if (fech != null && !errorX)
                        {
                            d.columna[col] = fech.ToString("MM/dd/yyyy HH:mm:ss");
                        }
                        else
                        {
                            generarLogError("[" + titulo + "] (Linea: " + (i + 2) + ") Error al convertir la fecha " + d.columna[col]);
                            error = false;
                        }
                    }
                    catch (Exception e)
                    {
                        Console.WriteLine(e.Message);
                        generarLogError("[" + titulo + "] (Linea: " + (i + 2) + ") Error al convertir la fecha " + d.columna[col]);
                        error = false;
                    }
                }
                else
                {
                    if (d.columna[col].Length > 0)
                    {
                        generarLogError("[" + titulo + "] (Linea: " + (i + 2) + ") Error al convertir la fecha " + d.columna[col]);
                        error = false;
                    }
                }
            }
            return error;
        }
        public bool acomodarporFecha(String titulo)
        {
            bool error = true;
            int col = this.darColumnaPorTitulo(titulo);
            if (col == -1)
            {
                generarLogError("[" + titulo + "] (Linea: " + (1) + ") Este campo no existe");
                return false;
            }
            for (int i=0; i<filas.Count; i++)
            {
                data d = filas[i];
                if (d.columna[col].Length > 7)
                {
                    try
                    {
                        DateTime fech = new DateTime();
                        fech = DateTime.Parse(d.columna[col]);
                        if (fech != null)
                        {
                            d.columna[col] = fech.ToString("MM/dd/yyyy");
                        }
                        else
                        {
                            generarLogError("["+titulo+"] (Linea: "+(i+2)+") Error al convertir la fecha " + d.columna[col]);
                            error = false;
                        }
                    }
                    catch (Exception e)
                    {
                        Console.WriteLine(e.Message);
                        generarLogError("[" + titulo + "] (Linea: " + (i + 2) + ") Error al convertir la fecha " + d.columna[col]);
                        error = false;
                    }
                }
                else
                {
                    if (d.columna[col].Length > 0)
                    {
                        generarLogError("[" + titulo + "] (Linea: " + (i + 2) + ") Error al convertir la fecha " + d.columna[col]);
                        error = false;
                    }
                }
            }
            return error;
        }
        public bool acomodarporZipCode(String titulo)
        {
            int col = this.darColumnaPorTitulo(titulo);
            if (col == -1)
            {
                generarLogError("[" + titulo + "] (Linea: " + (1) + ") Este campo no existe");
                return false;
            }
            foreach (data d in filas)
            {
                if (d.columna[col].Length < 5)
                {
                    String aux = "";
                    for (int i = d.columna[col].Length; i < 5; i++)
                    {
                        aux += "0";
                    }
                    aux += d.columna[col];
                    d.columna[col] = aux;
                }
            }
            return true;
        }
        public bool verificarVacios(String titulo, String textoReemplazo)
        {
            int col = titulos.IndexOf(titulo);
            if (col == -1)
            {
                generarLogError("[" + titulo + "] (Linea: " + (1) + ") Este campo no existe");
                return false;
            }
            foreach (data d in filas)
            {
                if (d.columna[col] == null)
                {
                    d.columna[col] = textoReemplazo;
                }
                else
                {
                    if (d.columna[col].Length == 0)
                    {
                        d.columna[col] = textoReemplazo;
                    }
                }
            }
            return true;
        }

        public bool verificarVacios(String titulo)
        {
            bool error = true;
            int col = titulos.IndexOf(titulo);
            if (col == -1)
            {
                generarLogError("[" + titulo + "] (Linea: " + (1) + ") Este campo no existe");
                return false;
            }
            for (int i=0; i<filas.Count; i++)
            {
                data d = filas[i];
                if (d.columna[col] == null)
                {
                    error = false;
                    generarLogError("[" + titulo + "] (Linea: " + (i + 2) + "--) Esta vacio");
                }
                else
                {
                    if (d.columna[col].Length==0)
                    {
                        generarLogError("[" + titulo + "] (Linea: " + (i + 2) + "**) Esta vacio");
                        error = false;
                    }
                }
            }
            return error;
        }
        public String valorObtenido(int pos, String titulo)
        {
            int col = titulos.IndexOf(titulo);
            if (col != -1)
            {
                List<String> selec = filas[pos].columna;
                return selec[col];
            }
            return null;
        }
        public void asignarValor(int pos, String titulo, String valor)
        {
            int col = titulos.IndexOf(titulo);
            if (col != -1)
            {
                filas[pos].columna[col] = valor;
            }
        }
        private String titulosToString()
        {
            String aux = "";
            for (int i = 0; i < titulos.Count-1; i++)
            {
                aux = aux + titulos[i] + ",";
            }
            aux = aux + titulos.Last();
            return aux;
        }
        public void guardarArchivo()
        {
            FileInfo fi = new FileInfo(this.archivo);
            
            //String arch = this.archivo + "_gen.csv";
            System.IO.Directory.CreateDirectory(fi.Directory + "\\Resultado");
            String arch = fi.Directory + "\\Resultado\\" + fi.Name;
            StreamWriter sw = new StreamWriter(arch, false, Encoding.Default);
            sw.WriteLine(titulosToString());
            for (int i = 0; i < filas.Count; i++)
            {
                sw.WriteLine(filas[i].filaToString());
            }
            sw.Close();
        }
        public void abrirArchivo()
        {
            StreamReader sr = new StreamReader(this.archivo,Encoding.Default);
            String linea = "";
            int cont = 0;
            int cantCol=0;
            //String[] l = verificar.atributosZipCode();
            this.filas = new List<data>();
            while (linea != null)
            {
                linea = sr.ReadLine();
                if (linea != null)
                {
                    //Console.WriteLine(linea);
                    ++cont;
                    String[] vector = linea.Split(',');
                    if (cont == 1)
                    {
                        //generando las columnas
                        titulos = vector.ToList<String>();
                        cantCol = titulos.Count;
                        this.numeroColumnas = titulos.Count;
                        //Console.WriteLine("--"+titulos.Count+" ->"+titulos.Last());
                    }
                    else
                    {
                        List<String> col = vector.ToList<String>();
                        List<String> col2 = new List<String>();
                        for (int i = 0; i < col.Count; i++)
                        {
                            String aux = col[i];
                            String aux2="";
                            
                            if (aux.Length > 0)
                            {
                                if (aux[0] == '\"' && aux[aux.Length - 1] == '\"')
                                {
                                    col2.Add(aux);
                                }
                                else
                                {
                                    if (aux[0] != '\"' && aux[aux.Length - 1] != '\"')
                                    {
                                        col2.Add(aux);
                                    }
                                    else
                                    {
                                        if (i + 1 < col.Count)
                                        {
                                            aux2 = col[i + 1];
                                           // Console.WriteLine(linea);
                                           // if (aux2.Length > 0)
                                            //{
                                                if ((aux[0] == '\"' && aux[aux.Length - 1] != '\"')) 
                                                {
                                                    if (aux2.Length > 0)
                                                    {
                                                        if ((aux2[0] != '\"' && aux2[aux2.Length - 1] == '\"'))
                                                        {
                                                            if (aux2[0] == ' ')
                                                            {
                                                                col2.Add(aux + "," + aux2);
                                                            }
                                                            else
                                                            {
                                                                col2.Add(aux + ", " + aux2);
                                                            }
                                                        }
                                                        else
                                                        {
                                                                //empezamos a buscar
                                                                String cadena = aux + ",";
                                                                bool enc = false;
                                                                for (int j = i + 1; j < col.Count && !enc; j++)
                                                                {
                                                                    aux2 = col[j];
                                                                    cadena += aux2;
                                                                    i++;
                                                                    if (aux2.Length > 0)
                                                                    {
                                                                        if (aux2[aux2.Length - 1] == '\"')
                                                                        {
                                                                            enc = true;
                                                                        }
                                                                        else
                                                                        {
                                                                            cadena += ",";
                                                                        }
                                                                    }
                                                                    else
                                                                    {
                                                                        cadena += ",";
                                                                    }
                                                                }
                                                                col2.Add(cadena);
                                                            
                                                        }
                                                    }
                                                    else
                                                    {
                                                            //empezamos a buscar
                                                            String cadena = aux + ",";
                                                            bool enc = false;
                                                            for (int j = i + 1; j < col.Count && !enc; j++)
                                                            {
                                                                aux2 = col[j];
                                                                cadena += aux2;
                                                                i++;
                                                                if (aux2.Length > 0)
                                                                {
                                                                    if (aux2[aux2.Length - 1] == '\"')
                                                                    {
                                                                        enc = true;
                                                                    }
                                                                    else
                                                                    {
                                                                        cadena += ",";
                                                                    }
                                                                }
                                                                else
                                                                {
                                                                    cadena += ",";
                                                                }
                                                            }
                                                            col2.Add(cadena);
                                                        

                                                    }
                                                    
                                                }
                                                else
                                                {
                                                }
                                           /* }
                                            else
                                            {

                                            }*/
                                        }
                                    }
                                }
                            }
                            else
                            {
                                col2.Add(aux);
                            }
                        }

                        //Console.WriteLine("Total "+cont+" -> "+col2.Count+" ("+col.Count+")");
                        List<String> col3 = new List<String>(this.numeroColumnas);
                        for (int i = 0; i < this.numeroColumnas; i++)
                        {
                            col3.Add("");
                        }
                        for (int i = 0; i < col2.Count; i++)
                        {
                            col3[i] = col2[i];
                        }
                        //Console.WriteLine("Total >>" + cont + " -> " + col3.Count);
                        data datfila = new data(this.numeroColumnas);
                        datfila.columna = col3;
                        filas.Add(datfila);
                    }
                }
            }
            sr.Close();
            //guardarArchivo();
            analizarColumnas();
        }
    }
    public class data
    {
        public List<String> columna;
        public data(int totColumnas)
        {
            columna = new List<String>(totColumnas);
        }
        public String dato(int pos)
        {
            if (pos >= columna.Count)
                return null;
            return columna[pos];
        }
        public void asignarValor(int pos, String val)
        {
            if (pos >= columna.Count)
                return;
            columna[pos] = val;
        }
        public String filaToString()
        {
            String aux = "";
            for (int i = 0; i < columna.Count - 1; i++)
            {
                aux = aux + columna[i] + ",";
            }
            aux = aux + columna.Last();
            return aux;
        }
    }
}
